package com.team.teamuserservice.websocket.service;

import cn.hutool.json.JSONUtil;
import com.team.teamuserservice.annotation.WebsocketMessageType;
import com.team.teamuserservice.entity.dto.UserLocation;
import com.team.teamuserservice.entity.dto.WebsocketMessage;
import com.team.teamuserservice.entity.po.BizRescueTask;
import com.team.teamuserservice.service.DelayMessageService;
import com.team.teamuserservice.service.IBizRescueTaskService;
import com.team.teamuserservice.uitls.MessageType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.team.teamuserservice.websocket.RescueWebsocketHandler.rescueMap;
import static com.team.teamuserservice.websocket.RescueWebsocketHandler.userSessionMap;
import static com.team.teamuserservice.uitls.IdGenerator.generateLongId;

@Slf4j
@Component
@RequiredArgsConstructor
@WebsocketMessageType(MessageType.REQUEST)
public class UserMessageHandler implements MessageHandler{

    private final RedisTemplate<String, Object> redisTemplate;
    private final IBizRescueTaskService bizRescueTaskService;
    private final DelayMessageService delayMessageService;

    private static final String MERCHANT_KEY = "merchantId";

    // 线程池用于异步处理
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);

    @Override
    public void handleMessage(WebSocketSession session, WebsocketMessage message) throws IOException {
        //这个是接收到用户发的消息
        //用户一旦连接就会发送地址信息 , 其中包括用户id , 以及经纬度
        UserLocation userLocation = (UserLocation) message.getMessage();
        if (userLocation == null) {
            return;
        }

        //这个时候就可以先创建对应的救援订单信息了
        BizRescueTask bizRescueTask = new BizRescueTask()
                //生成一个随机的id
                .setId(generateLongId())
                .setUserId(userLocation.getUserId())
                .setLongitude(BigDecimal.valueOf(userLocation.getLongitude()))
                .setLatitude(BigDecimal.valueOf(userLocation.getLatitude()))
                .setStatus("0")
                .setCreateTime(LocalDateTime.now());
        bizRescueTaskService.getBaseMapper().insert(bizRescueTask);

        //用户也要加入对应的map
        userSessionMap.put(userLocation.getUserId(), session);

        //广播给2KM以内的商家
        tellMerchant(userLocation);

        // 异步发送延迟广播任务
        executor.submit(() -> {
            try {
                // 1分钟后广播5km以内商家
                delayMessageService.send5kmBroadcastMessage(userLocation, bizRescueTask.getId());
                
                // 2分钟后广播10km以内商家
                delayMessageService.send10kmBroadcastMessage(userLocation, bizRescueTask.getId());
            } catch (Exception e) {
                // 记录错误日志，但不影响主流程
                System.err.println("完蛋了,消息都tm发送失败了: " + e.getMessage());
            }
        });
    }

    //广播给2KM以内的商家
    private void tellMerchant(UserLocation userLocation) throws IOException {
        GeoResults<RedisGeoCommands.GeoLocation<Object>> geos = redisTemplate.opsForGeo().radius(MERCHANT_KEY,
                new Circle(new Point(userLocation.getLongitude(), userLocation.getLatitude()), 3000)
        );
        log.info("geos: " + geos);
        if (geos != null) {
            for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult : geos) {
                String rescueMerchant = geoResult.getContent().getName().toString();

                    log.info("发送给商家: " + rescueMerchant);

                    Long merchantId = Long.valueOf(rescueMerchant);
                    
                    //获取该商家的 session
                    String jsonStr = JSONUtil.toJsonStr(userLocation);

                    //从map中获取该商家的 session
                    WebSocketSession webSocketSession = rescueMap.get(merchantId);
                    log.info("发送给商家的merchantId: " + merchantId);

                    //发送消息给该商家，注意这里的发送给商家是发送到前端商家的页面
                    if (webSocketSession != null && webSocketSession.isOpen()) {
                        webSocketSession.sendMessage(new TextMessage(jsonStr));
                    }
                }
            }
        }



    }

